#ifndef _HTTPSESSION_HPP_
#define _HTTPSESSION_HPP_

#include "jhdefs.hpp"
#include "stdlib/timespan.hpp"
#include "stdlib/exception.hpp"
using JHCPP::stdlib::CTimeSpan;
using JHCPP::stdlib::CException;
#include "utils/any.hpp"
using JHCPP::utils::CAny;
#include "net/StreamSocket.hpp"
#include "net/SocketAddress.hpp"

NET_NAMESPACE_BEGIN

class CHTTPSession
{
public:
	void setKeepAlive(bool keepAlive);
	bool getKeepAlive() const;

	void setTimeout(const CTimeSpan& timeout);
	CTimeSpan getTimeout() const;

	bool connected() const;
	virtual void abort();
	
	const CException* networkException() const;

	void attachSessionData(const CAny& data);
	const CAny& sessionData() const;

	enum
	{
		HTTP_PORT = 80
	};

	CStreamSocket detachSocket();
	CStreamSocket& socket();


protected:
	CHTTPSession();
	CHTTPSession(const CStreamSocket& socket);
	CHTTPSession(const CStreamSocket& socket, bool keepAlive);
	virtual ~CHTTPSession();


	int get();
	int peek();

	virtual int read(char* buffer, std::streamsize length);
	virtual int write(const char* buffer, std::streamsize length);

	int receive(char* buffer, int length);
	int buffered() const;
	void refill();

	virtual void connect(const CSocketAddress& address);
	void attachSocket(const CStreamSocket& socket);
	void close();

	void setException(const CException& exc);
	void clearException();

private:
	enum
	{
		HTTP_DEFAULT_TIMEOUT = 60000000
	};

	CHTTPSession(const CHTTPSession&);
	CHTTPSession& operator = (const CHTTPSession&);

	CStreamSocket	m_socket;
	char*			m_pBuffer;
	char*			m_pCurrent;
	char*			m_pEnd;
	bool			m_keepAlive;
	CTimeSpan		m_timeout;
	CException*		m_pException;
	CAny			m_data;

	friend class CHTTPStreamBuf;
	friend class CHTTPHeaderStreamBuf;
	friend class CHTTPFixedLengthStreamBuf;
	friend class CHTTPChunkedStreamBuf;
};

NET_NAMESPACE_END

#endif
